package jdbc;

import utils.ConnectionHandler;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.Properties;

/*
* 单例模式
* 数据源(数据库连接池)
* */
public class DataSource {
    private String url = null;
    private String user = null;
    private String pwd = null;
    private int initCount = 5;  // 初始化连接个数
    private int maxCount = 10;  // 最大连接个数
    private int currentCount = 0; // 当前使用的连接个数

    private LinkedList<Connection> connectionPool = new LinkedList<Connection>(); // 初始化连接池

    private static DataSource dataSource = new DataSource(); // 实现单例模式

    {
        Properties properties = new Properties();
        InputStream in = DataSource.class.getClassLoader().getResourceAsStream("datasource.properties");
        try {
            properties.load(in);
            url = properties.getProperty("jdbc.url");
            user = properties.getProperty("jdbc.user");
            pwd = properties.getProperty("jdbc.pwd");
            try {
                initCount = Integer.parseInt(properties.getProperty("jdbc.initCount"));
                maxCount = Integer.parseInt(properties.getProperty("jdbc.maxCount"));
            }catch (NumberFormatException e){
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    static {
        Properties properties = new Properties();
        InputStream in = DataSource.class.getClassLoader().getResourceAsStream("datasource.properties");
        try {
            properties.load(in);
            try {
                Class.forName(properties.getProperty("jdbc.driver"));
            } catch (ClassNotFoundException e) {
                throw new RuntimeException("注册驱动失败!");
            }
        } catch (IOException e) {
            throw new RuntimeException("读取数据库配置文件失败!");
        }
    }

    private DataSource(){
        /*
        * 初始化5个数据库连接
        * */
        for (int i=0; i<initCount; i++) {
            try {
                Connection conn = createConnection();
                connectionPool.addLast(conn);
            } catch (SQLException e) {
                throw new ExceptionInInitializerError(e);
            }
        }

    }

    public static DataSource getInstance(){
        return dataSource;
    }

    public Connection getConnection() throws SQLException{
        /*
        * 从连接池中取连接
        * */
        if (connectionPool.size() > 0) {
            currentCount++;
            return connectionPool.removeFirst();
        }else {
            if (currentCount <= maxCount) {
                try {
                    Connection conn = createConnection();
                    currentCount++;
                    return conn;
                } catch (SQLException e) {
                    throw new ExceptionInInitializerError(e);
                }
            }
            throw new SQLException("已经超过最大的连接了！");
        }

    }

    private Connection createConnection() throws SQLException {
        Connection conn = DriverManager.getConnection(url, user, pwd);
        ConnectionHandler connectionHandler = new ConnectionHandler(this);
        return (Connection) connectionHandler.bind(conn);
    }

    public void free(Connection conn){
        /*
        * 把连接放回连接池
        * */
        connectionPool.addLast(conn);
        currentCount--;
    }
}
